// 工具注册中心
import { BaseTool, ToolRegistry } from './types';
import { CalculatorTool } from './implementations/calculator';
import { SearchTool } from './implementations/search';
import { PageFetcher } from './implementations/page-fetcher';
import { MCPClientTool } from './implementations/mcp-client';

export class ToolManager {
  private tools: ToolRegistry = {};
  private mcpRemoteTools: Map<string, any> = new Map(); // 存储MCP远程工具信息
  private mcpClientTool: MCPClientTool | null = null; // 内部MCP客户端，不暴露给AI
  private chatManagerRef: any = null; // ChatManager引用，用于触发系统提示词更新

  constructor() {
    this.registerDefaultTools();
    this.initializeMCPClient();
  }

  private registerDefaultTools() {
    // 现有工具 - 这些会暴露给AI
    this.registerTool(new CalculatorTool());
    this.registerTool(new SearchTool());
    this.registerTool(new PageFetcher());
    // 注意：不再将mcp-client注册为AI可见工具
  }

  private initializeMCPClient() {
    // 创建内部MCP客户端，不暴露给AI
    this.mcpClientTool = new MCPClientTool();
    this.mcpClientTool.setToolManagerRef(this);
  }

  // 设置ChatManager引用（从ChatManager调用）
  setChatManagerRef(chatManager: any): void {
    this.chatManagerRef = chatManager;
  }

  // 新增：注册MCP远程工具
  registerMCPRemoteTool(serverName: string, toolName: string, toolInfo: any): void {
    const fullToolName = `${serverName}::${toolName}`;
    this.mcpRemoteTools.set(fullToolName, {
      serverName,
      toolName,
      description: toolInfo.description || '',
      parameters: toolInfo.inputSchema || {},
      originalInfo: toolInfo
    });
  }
  // 新增：MCP连接后更新系统提示词
  updateSystemPromptAfterMCPConnection(): void {
    // 使用ChatManager的updateSystemPromptForMCP方法来触发更新
    if (this.chatManagerRef && this.chatManagerRef.updateSystemPromptForMCP) {
      this.chatManagerRef.updateSystemPromptForMCP();
  
    }
  }


  // 内部方法：连接MCP服务器（由ChatManager调用）
  async _connectMCPServer(serverName: string, command: string, cwd?: string): Promise<boolean> {
    if (!this.mcpClientTool) {
      throw new Error('MCP客户端未初始化');
    }
    return await this.mcpClientTool.getMCPManager().connectToServer(serverName, command, cwd);
  }

  // 内部方法：断开MCP服务器（由ChatManager调用）  
  async _disconnectMCPServer(serverName: string): Promise<void> {
    if (!this.mcpClientTool) {
      throw new Error('MCP客户端未初始化');
    }
    await this.mcpClientTool.getMCPManager().disconnectFromServer(serverName);
  }

  // 内部方法：获取MCP管理器（供内部使用）
  _getMCPManager() {
    return this.mcpClientTool?.getMCPManager();
  }

  // 新增：移除MCP远程工具
  unregisterMCPRemoteTool(serverName: string, toolName?: string): void {
    if (toolName) {
      const fullToolName = `${serverName}::${toolName}`;
      this.mcpRemoteTools.delete(fullToolName);
   
    } else {
      // 移除该服务器的所有工具
      for (const [key, value] of this.mcpRemoteTools) {
        if (value.serverName === serverName) {
          this.mcpRemoteTools.delete(key);
     
        }
      }
    }
  }

  // 新增：获取所有工具（包括MCP远程工具）
  getAllToolsIncludingMCP(): any[] {
    const localTools = this.getAllTools();
    const mcpTools = Array.from(this.mcpRemoteTools.values()).map(mcpTool => ({
      name: `${mcpTool.serverName}::${mcpTool.toolName}`,
      description: mcpTool.description,
      parameters: {
        type: 'object',
        properties: mcpTool.parameters.properties || {},
        required: mcpTool.parameters.required || []
      },
      isMCPRemote: true,
      serverName: mcpTool.serverName,
      originalToolName: mcpTool.toolName
    }));
    return [...localTools, ...mcpTools];
  }

  registerTool(tool: BaseTool) {
    this.tools[tool.name] = tool;
    console.log(`工具已注册: ${tool.name}`);
  }

  unregisterTool(name: string): boolean {
    if (this.tools[name]) {
      delete this.tools[name];
      console.log(`工具已移除: ${name}`);
      return true;
    }
    return false;
  }

  getTool(name: string): BaseTool | undefined {
    return this.tools[name];
  }

  getAllTools(): BaseTool[] {
    return Object.values(this.tools);
  }

  getToolDefinitions() {
    return this.getAllTools().map(tool => tool.getDefinition());
  }

  async executeTool(name: string, args: Record<string, any>): Promise<string> {
    // 首先检查是否是MCP远程工具
    if (name.includes('::')) {
      return await this.executeMCPRemoteTool(name, args);
    }
    
    // 处理本地工具
    const tool = this.getTool(name);
    if (!tool) {
      throw new Error(`工具 "${name}" 未找到`);
    }
    
    try {
      console.log(`\n🔧 执行工具: ${name}`);
      console.log(`📋 参数:`, args);
      
      const result = await tool.execute(args);
      
      console.log(`✅ 工具执行完成`);
      return result;
    } catch (error) {
      const errorMsg = `工具 "${name}" 执行失败: ${error instanceof Error ? error.message : '未知错误'}`;
      console.log(`❌ ${errorMsg}`);
      return errorMsg;
    }
  }

  // 新增：执行MCP远程工具
  private async executeMCPRemoteTool(fullToolName: string, args: Record<string, any>): Promise<string> {
    const mcpTool = this.mcpRemoteTools.get(fullToolName);
    if (!mcpTool) {
      throw new Error(`MCP远程工具 "${fullToolName}" 未找到`);
    }

    try {
      console.log(`\n🌐 执行MCP远程工具: ${fullToolName}`);
      console.log(`📋 参数:`, args);

      // 使用内部MCP管理器调用远程工具
      const mcpManager = this._getMCPManager();
      if (!mcpManager) {
        throw new Error('MCP管理器未初始化');
      }

      const result = await mcpManager.callRemoteTool(
        mcpTool.serverName,
        mcpTool.toolName,
        args
      );

      console.log(`✅ MCP远程工具执行完成`);
      return result;
    } catch (error) {
      const errorMsg = `MCP远程工具 "${fullToolName}" 执行失败: ${error instanceof Error ? error.message : '未知错误'}`;
      console.log(`❌ ${errorMsg}`);
      return errorMsg;
    }
  }

  // 修改：生成包含MCP远程工具的工具提示词
  generateToolPrompt(): string {
    const regularToolsDescription = this.generateRegularToolPrompt();
    const mcpToolsDescription = this.generateMCPPrompt();
    
    // 组合两种工具的描述
    const allToolsDescription = [regularToolsDescription, mcpToolsDescription]
      .filter(desc => desc.trim()) // 过滤空描述
      .join('\n\n');
       
    return `

可用工具：
${allToolsDescription}

工具调用格式：
当你需要使用工具时，请严格按照以下XML格式输出：
<function_calls>
<invoke name="工具名称">
<parameter name="参数名">参数值</parameter>
</invoke>
</function_calls>

重要提示：
1. 目前支持一次只能调用一个工具，当调用工具后，你需要停止输出，这样工具的调用结果才能在下一轮对话中返回给你。
2. 工具调用放在 <function_calls> 标签中
3. 参数值直接写在 <parameter> 标签内，解析器会直接提取其中的文字，无需任何转义。
4. 如果用户明确要求"调用XX工具"，请立即调用对应工具
5. 调用工具后等待结果，然后基于结果回答用户
 

示例：
用户："计算 2+3"
你应该回复：我来为您计算 2+3
<function_calls>
<invoke name="calculator">
<parameter name="expression">2+3</parameter>
</invoke>
</function_calls>

代码的示例：
在参数中编写xml，jsx,tsx等，都不需要对xml标签进行转义，直接写入即可，
例如 要写入
<div>
  <h1>Hello, World!</h1>
</div>

<function_calls>
<invoke name="some_edit_tool_name">
<parameter name="content">
<div> 
  <h1>Hello, World!</h1>
</div>
</parameter>
</invoke>
</function_calls>

错误示范
<function_calls>
<invoke name="some_edit_tool_name">
<parameter name="content">
&lt;div&gt;
  &lt;h1&gt;Hello, World!&lt;/h1&gt;
&lt;/div&gt;
</parameter>
</invoke>
</function_calls>


注意 不需要转义！
`;
  }

  // 新增：生成常规本地工具提示词
  private generateRegularToolPrompt(): string {
    const localTools = this.getAllTools();
    if (localTools.length === 0) return '';

    return localTools.map(tool => {
      const params = Object.entries(tool.parameters.properties)
        .map(([name, config]: [string, any]) => `  - ${name} (${config.type}): ${config.description}`)
        .join('\n');
      
      return `**${tool.name}**
描述: ${tool.description}
参数:
${params}`;
    }).join('\n\n');
  }

  // 新增：生成MCP远程工具提示词
  private generateMCPPrompt(): string {
    if (this.mcpRemoteTools.size === 0) return '';

    const mcpTools = Array.from(this.mcpRemoteTools.values()).map(mcpTool => {
      let params = '';
      if (mcpTool.parameters && mcpTool.parameters.properties) {
        params = Object.entries(mcpTool.parameters.properties)
          .map(([name, config]: [string, any]) => `  - ${name} (${config.type || 'string'}): ${config.description || ''}`)
          .join('\n');
      }
      
      return `**${mcpTool.serverName}::${mcpTool.toolName}** 🌐 [MCP远程工具]
描述: ${mcpTool.description}
服务器: ${mcpTool.serverName}
参数:
${params || '  无参数'}`;
    });

    return mcpTools.join('\n\n');
  }

  // 保留原有的方法用于向后兼容
  private generateToolsDescription(tools: BaseTool[]): string {
    return tools.map(tool => {
      const params = Object.entries(tool.parameters.properties)
        .map(([name, config]: [string, any]) => `  - ${name} (${config.type}): ${config.description}`)
        .join('\n');
      
      return `**${tool.name}**
描述: ${tool.description}
参数:
${params}`;
    }).join('\n\n');
  }

  listAvailableTools(): string {
    const tools = this.getAllTools();
    let result = '\n=== 可用工具列表 ===\n';
    
    tools.forEach((tool, index) => {
      result += `${index + 1}. ${tool.name}\n`;
      result += `   描述: ${tool.description}\n`;
      result += `   参数: ${JSON.stringify(tool.parameters.properties, null, 2)}\n\n`;
    });
    
    return result;
  }

  getToolCount(): number {
    return Object.keys(this.tools).length;
  }

  hasTools(): boolean {
    return this.getToolCount() > 0;
  }

  clearAllTools() {
    this.tools = {};
    console.log('所有工具已清除');
  }
}

// 移除全局实例导出，现在通过依赖注入使用
